var objGame = {
    
    // design from: http://steffengerlach.de/gomoku/index.html
    
    my_id           : null,
    step_type       : null, // if i send the game request, my oppenent start the game.
                            // 0 - start, first (x) ; 1 - second (o)
    paper           : null,
    p1spot          : null,
    p1winspot       : null,
    p2spot          : null,
    p2winspot       : null,
    map             : null, // array: 0-empty, 1-reserved
    my_step         : false,
    hover_rect      : null,
    
    SQUARE_SIZE     : 30,
    ROWNUM          : 18,
    COLNUM          : 18,

    opp_id          : null, // oppenent's name
    opp_name        : null, // oppenent's name
    game_over       : true,
    
    init :
    function(_this, step_type)
    {
        if (_this.paper !== null)
        {
            _this.paper.clear();
        }
        
        _this.step_type     = parseInt(step_type, 10);
        _this.map           = new Array();
        _this.hover_rect    = null;
        _this.my_step       = (step_type === '0') ? true : false;

        for (var i = 0; i < _this.ROWNUM; ++i)
        {
            _this.map[i] = new Array();
            for (var j = 0; j < _this.COLNUM; ++j)
            {
                _this.map[i][j] = 0;
            }
        }
        
        if (step_type === '0')
            $('#message').text("Its your turn!");
        else
            $('#message').text(_this.opp_name + "'s turn!");
    },
    
    drawLine :
    function (_this, mx, my, lx, ly, stroke_width, stroke_color)
    {
        if (stroke_width == undefined) stroke_width = 1;
        if (stroke_color == undefined) stroke_color = '#fff';
        _this.paper.path("M"+mx+" "+my+"L"+lx+" "+ly).attr({stroke: stroke_color, 'stroke-width': stroke_width, opacity: 0.9});
    },
    
    drawStep :
    function (_this, x, y, type, p1spot, p2spot)
    {
        if (p1spot == undefined) p1spot = _this.p1spot;
        if (p2spot == undefined) p2spot = _this.p2spot;
        
        var pos_x = x * _this.SQUARE_SIZE - _this.SQUARE_SIZE;
        var pos_y = y * _this.SQUARE_SIZE - _this.SQUARE_SIZE;

        if (type === 0)
        {
            p1spot.clone().attr({   x: pos_x - _this.SQUARE_SIZE/2, 
                                    y: pos_y - _this.SQUARE_SIZE/2});
        }
        else
        {
            p2spot.clone().attr({   x: pos_x - _this.SQUARE_SIZE/2, 
                                    y: pos_y - _this.SQUARE_SIZE/2});
        }
    },
    
    sendStep :
    function(_this, x, y)
    {
        $('#message').text(_this.opp_name + "'s turn!");
        
        // send my next step
        _this.my_step   = false;
        _this.map[x+2][y+2] = 1;
        objWebSocket.socket.send(objCommands.GAME_STEP +
                                objCommandee.setPlayer(_this.my_id) +
                                x.toString().lpad("0", 2) +
                                y.toString().lpad("0", 2));
    },
    
    getStep :
    function(_this, x, y)
    {
        $('#message').text("Its your turn!");
        
        // get my oppenent's next step!
        _this.my_step   = true;
        _this.map[x+2][y+2] = 1;
        _this.drawStep(_this, x+3, y+3, _this.step_type === 1 ? 0 : 1);
    },
    
    drawFiveInARow :
    function(_this, type, step_type, points)
    {
        // type: 8 (vertical), 7 (left diagonal), 9 (right diagonal), 4 (horizontal)
        // points: bottom up, top down (2 points)
        
        points.p1x = parseInt(points.p1x, 10) + 3;
        points.p1y = parseInt(points.p1y, 10) + 3;
        
        switch (type)
        {
            case '8':
            {
                for (var i = 0; i < 5; ++i)
                {
                    _this.drawStep( objGame, points.p1x, points.p1y+i, step_type,
                                    _this.p1winspot, _this.p2winspot);
                }
            }
            break;
            
            case '4':
            {
                for (i = 0; i < 5; ++i)
                {
                    console.log((points.p1x+i));
                    _this.drawStep( objGame, points.p1x+i, points.p1y, step_type,
                                    _this.p1winspot, _this.p2winspot);
                }
            }
            break;
            
            case '7':
            {
                for (i = 0; i < 5; ++i)
                {
                    _this.drawStep( objGame, points.p1x+i, points.p1y+i, step_type,
                                    _this.p1winspot, _this.p2winspot);
                }
            }
            break;
            
            case '9':
            {
                for (i = 0; i < 5; ++i)
                {
                    _this.drawStep( objGame, points.p1x-i, points.p1y+i, step_type,
                                    _this.p1winspot, _this.p2winspot);
                }
            }
            break;
        }
    },
    
    startGame :
    function(_this, first)
    {
        if (first == undefined) first = false;
        
        _this.game_over = false;
        
        // paper
        if (_this.paper === null)
        _this.paper = Raphael("paper", _this.SQUARE_SIZE*_this.ROWNUM, _this.SQUARE_SIZE*_this.COLNUM);
        _this.p1spot = _this.paper.image(  "assets/images/p1.png",
                                            0, 0, 30, 30);
        _this.p2spot = _this.paper.image(  "assets/images/p2.png",
                                            0, 0, 30, 30);
        _this.p1winspot = _this.paper.image("assets/images/p1win.png",
                                            0, 0, 30, 30);
        _this.p2winspot = _this.paper.image(  "assets/images/p2win.png",
                                            0, 0, 30, 30);
        // background
        var bg = _this.paper.image("assets/images/bg_wood.jpg", 0, 0, _this.SQUARE_SIZE*_this.ROWNUM, _this.SQUARE_SIZE*_this.COLNUM);
        // grid's mousemove cell
        _this.hover_rect    = _this.paper.rect(0, 0, _this.SQUARE_SIZE, _this.SQUARE_SIZE).hide();
        // full grid
        for (var i = 2; i < _this.ROWNUM-1; ++i)
        {
            _this.drawLine(_this, 2*_this.SQUARE_SIZE, i*_this.SQUARE_SIZE,
                            _this.SQUARE_SIZE*(_this.COLNUM-2), i*_this.SQUARE_SIZE);
        }
        for (i = 2; i < _this.COLNUM-1; ++i)
        {
            _this.drawLine(_this, i*_this.SQUARE_SIZE, 2*_this.SQUARE_SIZE,
                            i*_this.SQUARE_SIZE, _this.SQUARE_SIZE*(_this.ROWNUM-2));
        }
        
        if (first) return;
        
        // grid's cell on mousemove
        bg.mousemove(function (event) 
        {
            if (_this.my_step === false || _this.game_over) return;

            pos_x = parseInt((event.pageX+_this.SQUARE_SIZE/2 - _this.paper.canvas.offsetLeft) / _this.SQUARE_SIZE, 10);
            pos_y = parseInt((event.pageY+_this.SQUARE_SIZE/2 - _this.paper.canvas.offsetTop) / _this.SQUARE_SIZE, 10);
            if (pos_x < 2 || pos_x > 16 ||
                pos_y < 2 || pos_y > 16 ||
                _this.map[pos_x][pos_y] === 1)
            {
                _this.hover_rect.hide();
                return;
            }

            _this.hover_rect.attr({ x: pos_x * _this.SQUARE_SIZE - _this.SQUARE_SIZE/2,
                                    y: pos_y * _this.SQUARE_SIZE - _this.SQUARE_SIZE/2}).show();
        });
        // grid's cell click
        bg.click(function (event)
        {       
            if (_this.my_step === false || _this.game_over) return;
            
            pos_x = parseInt((event.pageX+_this.SQUARE_SIZE/2 - _this.paper.canvas.offsetLeft) / _this.SQUARE_SIZE, 10);
            pos_y = parseInt((event.pageY+_this.SQUARE_SIZE/2 - _this.paper.canvas.offsetTop) / _this.SQUARE_SIZE, 10);
            if (_this.map[pos_x][pos_y] === 1 ||
                pos_x < 2 || pos_x > 16 ||
                pos_y < 2 || pos_y > 16)
                return;
            _this.drawStep(_this, pos_x+1, pos_y+1, _this.step_type);
            _this.sendStep(_this, pos_x-2, pos_y-2);
            _this.hover_rect.hide();
        });
    }
};
